﻿using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Neo4jConnect.Traversal
{
    public class TraversalBuilder
    {
        private uint maxDepth = 1;
        private TraversalOrder order = TraversalOrder.BreadthFirst;
        private ReturnableEvaluator returnableEvaluator = null;
        private List<Tuple<Enum, RelationshipDirection>> relations;

        public TraversalBuilder()
        {
            relations = new List<Tuple<Enum, RelationshipDirection>>();
        }

        public TraversalBuilder WithOrder(TraversalOrder order)
        {
            this.order = order;
            return this;
        }

        public TraversalBuilder WithRelationship(Enum relationship)
        {
            return WithRelationship(relationship, RelationshipDirection.All);                        
        }

        public TraversalBuilder WithRelationship(Enum relationship, RelationshipDirection direction)
        {
            relations.Add(new Tuple<Enum, RelationshipDirection>(relationship, direction));
            return this;
        }

        public TraversalBuilder WithReturn(BuiltInReturnableEvaluatorType evaluatorType)
        {
            returnableEvaluator = new BuiltInReturnableEvaluator(evaluatorType);    
            return this;
        }

        public TraversalBuilder WithReturn(string javascript)
        {
            returnableEvaluator = new JavascriptReturnableEvaluator(javascript);
            return this;
        }

        public TraversalBuilder WithMaxDepth(uint maxDepth)
        {
            this.maxDepth = maxDepth;
            return this;
        }

        internal string Build()
        {
            var relationships = new JArray();
            foreach (var relation in relations)
            {
                dynamic relationship = new JObject();
                relationship.type = relation.Item1.ToString();
                relationship.direction = relation.Item2.GetDescription();                
                relationships.Add(relationship);                
            }

            dynamic obj = new JObject();
            obj.order = order.GetDescription();
            obj.relationships = relationships;
            obj["return_filter"] = returnableEvaluator.ToJson();
            obj["max_depth"] = maxDepth;

            return JsonConvert.SerializeObject(obj);            
        }       
    }
}
